package thread;

// wait notify 操作
// 保证加锁对象、wait和notify调用对象都是同一个！！！

public class Demo13 {
    public static void main(String[] args) {
        // 专门创建一个对象，保证等待和通知是同一个对象！
        Object o = new Object();

        // 第一个线程进行wait操作
        Thread t1 = new Thread(() -> {
            while (true) {
                synchronized (o) {
                    // 1.
                    System.out.println("wait 之前");
                    try {
                        // 等待
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 4. wait 加锁成功，继续执行
                    System.out.println("wait 之后");
                    // 一轮执行完毕 又开始循环下一轮！
                    // 下一轮会直接输出 wait之前，然后wait，然后开始另一个线程的调用，
                    // 但是此时另一个线程还处于上一个线程的休眠时间内，休眠时间结束后接着输出线程2中的内容，直到notify释放锁
                    // 。。。
                    // 循环操作
                }

                // 如果在这里加个休眠时间，则在wait被唤醒成功加锁后，需要等待6秒时间后才“wait之后”执行。
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();

        // 第二个线程进行notify操作
        Thread t2 = new Thread(() -> {
            while (true) {
                synchronized (o) {
                    // 2.
                    System.out.println("notify 之前");
                    // 此时唤醒wait，但是需要等待notify释放锁
                    o.notify();
                    // 3. 此时notify释放锁，wait尝试加锁 然后继续向后执行
                    System.out.println("notify 之后");
                }

                // 每次notify之后都休眠10秒
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t2.start();

        // wait进入等待之后，要等待notify调用将其唤醒，而wait想要重新加锁就需要等待notify释放锁完成！！
    }
}
